package com.wsm.common.aspect;

import com.alibaba.fastjson.JSON;
import com.wsm.common.exception.MyException;
import com.wsm.common.utils.DateUtils;
import com.wsm.common.utils.IPUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@Aspect
@Component
@Order(6)
public class WebLogAspect {

    private static final Logger logger = LoggerFactory.getLogger(WebLogAspect.class);

    @Pointcut("execution( * com.wsm.*.controller.*.*(..))")//两个..代表所有子目录，最后括号里的两个..代表所有参数
    public void logPointCut() {
    }

    @Around("logPointCut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object ob = pjp.proceed();
        long time = System.currentTimeMillis() - startTime;
        saveLog(pjp, time, JSON.toJSONString(ob));
        return ob;
    }

    /**
     * 保存日志
     *
     * @param joinPoint
     * @param time
     */
    @Async
    void saveLog(ProceedingJoinPoint joinPoint, long time, String result) {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        String ip = IPUtils.getIpAddr(request);
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String formatDate = DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN);
        //请求的 类名、方法名
        String className = joinPoint.getTarget().getClass().getName();
        String methodName = signature.getName();
        //请求的参数
        Object[] args = joinPoint.getArgs();
        StringBuffer stringBuffer = new StringBuffer();
        try {
            for (Object o : args) {
                stringBuffer.append(o.toString());
            }
        } catch (Exception e) {
            throw new MyException("aop打印方法日志失败");
        }
        logger.info("请求ip地址：{}，请求时间：{}，请求的类名为：{}，请求的方法为：{}，请求的参数为：{}，消耗时间为：{}，返回结果为：{}", ip, formatDate, className, methodName, stringBuffer, time, result);
    }
}
